﻿

//     Copyright (c) Narin Persad. All rights reserved.The MIT License (MIT)

// Copyright (c) 2014 Narin Persad

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. 

//-----------------------------------------------------------------------


(function ($) {

    var field = " li.file > .row > div:nth-of-type(1)";
    var filter = " li.file > .row > div:nth-of-type(2)";

    var conjunction = " li.file > .row > div:nth-of-type(3)";
    var plus = " li.file > .row > div:nth-of-type(5)";
    var remove = " li.file > .row > div:nth-of-type(6)";
    var queryArray = new Array();
    $.SimpleQuery = function (el, options) {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);


        // Add a reverse reference to the DOM object
        base.$el.data("SimpleQuery", base);



        base.init = function () {
            base.options = $.extend({}, $.SimpleQuery.defaultOptions, options, { $template: $(el).find('.file').first().clone(false) });

            // Put your initialization code here
            base.$el.find('.autodrop').autodrop();
            updateElement($(el), this.options);
        };

        // build query
        base.buildQuery = function () {
            var treeRoot = this.$el.find('ol').first();

            var hasError = _validate(treeRoot);

            if (hasError) return false;

            _buildQueryTree(treeRoot, 0, queryArray, '');

            return queryArray;
        };

        //clear query
        base.clearQuery = function () {
            var treeRoot = this.$el.find('li.file ~ li').remove();

            //this.$el.find(':input[class*="Query"]').val('');
            this.$el.find(':input').val('');
            this.$el.find('.Field > button:first-of-type ').text('Field');
            this.$el.find('.Operation > button:first-of-type').text('Filter');
            var conjunctionButton = this.$el.find('.Conjunction > button:first-of-type');
            conjunctionButton.empty();
            conjunctionButton.append('<span data-bind="label"><i class="glyphicon glyphicon-magnet"></i></span>');
        }

        // Run initializer
        base.init();


    };

    $.SimpleQuery.defaultOptions = {
    };

    $.fn.SimpleQuery = function (options) {
        return this.each(function () {
            (new $.SimpleQuery(this, options));
        });
    };


    // This function breaks the chain, but returns
    // the SimpleQuery if it has been attached to the object.
    $.fn.getSimpleQuery = function () {
        var data = this.data("SimpleQuery");
        return data;
    };

    var _subControl = '<input type="hidden" data-name="condition.isSubCondition" class="Query" value="true" />'
       + '<div class="btn-group subConnector" data-toggle="buttons">'
       + '<label class="btn btn-primary btn-xs" data-toggle="tooltip" title="The conjunction that will be used to connect the adjacent clause." data-placement="right">'
       + '<input type="radio" data-name="condition.Conjunction" class="Query" checked="checked" value="AND">  AND'
       + '</label>'
       + '<label class="btn btn-primary btn-xs" data-toggle="tooltip" title="The conjunction that will be used to connect the adjacent clause." data-placement="right">'
       + '<input type="radio" data-name="condition.Conjunction" class="Query" value="OR" /> OR'
       + '</label>'
       + '</div>'

    //var _subtraction = '<div class="btn-group removeQueryControl"><button class="btn btn-default btn-sm dropdown-toggle data-toggle="dropdown"><i class="glpyhicon glyphicon-minus"/></button></div>';

    //Private functions
    function _validate(treeRoot) {
        var hasError = false;
        treeRoot.find('.Field input[type="text"], .Operation input[type="text"]').each(function () {
            var value = $(this).val();
            if (value === "") {
                $(this).closest('.input-group').addClass('has-error');
                hasError = true;
            }
            else {
                $(this).closest('.input-group').removeClass('has-error');
            }
        });

        treeRoot.find('.btn-group.Conjunction:visible button span').each(function () {
            var value = $(this).text();
            if (value === "") {
                $(this).closest('.btn-group').addClass('has-error');
                hasError = true;
            } else {
                $(this).closest('.btn-group').removeClass('has-error');
            }
        });
        return hasError;
    }

    function updateElement(element, options) {
        //Manipulate element here...   
        element.on('click', 'a', function (e) {
            e.preventDefault();
        });
        $('.QueryTree').on('focusout', '.Field input[type="text"], .Operation input[type="text"]', function () {
            var value = $(this).val();
            if (value === "") {
                $(this).closest('.input-group').addClass('has-error');
                hasError = true;
            }
            else {
                $(this).closest('.input-group').removeClass('has-error');
            }
        });

        $('.QueryTree').on('mouseout', '.btn-group.Conjunction button', function () {
            var value = $(this).find('span').text();
            if (value === "") {
                $(this).closest('.btn-group').addClass('has-error');
                hasError = true;
            } else {
                $(this).closest('.btn-group').removeClass('has-error');
            }
        });
        _setAddQueryControl(element, options);
        _setRemoveQueryControl(element);
        _setClickFolderHeader(element);
        _setClickNotAddOrRemove(element);
    }

    function _setRemoveQueryControl(element) {
        element.on('click', '.Remove', function () {
            var deleteItem = $(this).closest('ol');
            $(this).closest('.file').remove();
            _deleteQueryControlRec(deleteItem);
        });
    }
    function _setClickNotAddOrRemove(element) {
        element.on('click', '.btn-group:not(.Add,.Remove) > .dropdown-menu li', function (event) {
            var $target = $(event.currentTarget);

            $target.closest('.btn-group')
               .find('[data-bind="label"]').text($target.text())
               .end()
               .children('.dropdown-toggle').dropdown('toggle');

            if ($.trim($target.text()) !== "") {
                $(this).closest('.btn-group').removeClass('has-error');
            }

            $target.closest('.btn-group').find('input').first().val($target.text());
            return false;
        });
    }
    function _setClickFolderHeader(element) {
        element.on('click', '.folderHeader> input', function () {
            $(this).prev().find(':first-child')[0].className = (this.checked ? 'glyphicon glyphicon-folder-open' : 'glyphicon glyphicon-folder-close');
        });
    }
    function _deleteQueryControlRec(deleteItem) {
        var parent = deleteItem.parents('ol')[0];
        if (deleteItem.children('li').length == 0) {
            deleteItem.parent().remove();
            _deleteQueryControlRec($(parent));
        }
    }
    function _indentControl(element) {
        //element.append(subControl)
        var ol = $('<ol></ol>').append(element);

        var li = $('<li class="folderHeader"></li>')
         .append('<label for=""><i class="glyphicon glyphicon-folder-close"></i> Condition</label>')
         .append('<input type="checkbox"/>')
         .append(ol)
         .append(_subControl);

        return li;


    }
    function _setAddQueryControl(element, options) {

        element.on('click', ".Add > .dropdown-menu >li", function () {

            var plusControl = $(this);
            var indent = plusControl.find('a')[0].innerHTML == '(';
            var template = options.$template.clone(false);
            //var template = element.find('.file').first().clone(false);
            template.find(':input').val('');
            template.find(field + ">button").text('Field');
            template.find(filter + " >button").text('Filter');

            var newControl = indent ? _indentControl(template) : template;
            template.find('.autodrop').autodrop();
            var file = plusControl.closest('.file').after(newControl);
        });
    }
    //Private function to set the input values in each row to the value in the adjacent dropdown/field
    function _buildQueryTree(ol, arrIndex, arr, subName) {

        var listItems = ol.children('li');


        listItems.each(function (index, element) {
            arr[index] = new Array();
            //end of the line

            arr[index] = {
                condition:
                    {
                        Field: null
                        , Operation: null
                        , Value: null
                        , Conjunction: null
                        , isSubCondition: null

                    }
                 , conditions: null
            };

            var el = $(element);

            if (el.hasClass('file')) {
                var inputs = $(el).find('input');

                inputs.each(function (indexEl, elementEl) {
                    var elementName = $(elementEl).attr('data-name');
                    var jsonName = subName + '[' + index + '].' + elementName.replace(/\..*\./, '.' + elementName + '.');
                    $(elementEl).attr('name', subName + '[' + index + '].' + elementName.replace(/\..*\./, '.' + elementName + '.'));


                    var elements = elementName.split('.');

                    var clauseProperty = '.' + elements[elements.length - 1]
                    arr[index].condition[elements[elements.length - 1]] = $(elementEl).val();
                });
            }
            else if (el.hasClass('folderHeader')) {
                var subConnector = $(el).children('.subConnector').find('input[data-name*="Conjunction"]');
                subConnector.each(function (index1, element1) {
                    var elementName = $(element1).attr('data-name');
                    $(element1).attr('name', subName + "[" + (index) + "]." + elementName);
                    arr[index].condition.Conjunction = $(element1).val();

                });

                var subbed = $(el).children('input[data-name*="isSubCondition"]');
                subbed.each(function (index2, element2) {
                    var subQueryName = $(element2).attr('data-name');
                    $(element2).attr('name', subName + "[" + (index) + "]." + subQueryName);
                    arr[index].condition.isSubCondition = $(element2).val();

                });


                arr[index].conditions = new Array();
                _buildQueryTree(el.children('ol'), index, arr[index].conditions, subName + "[" + (index) + "].conditions");
            }
        });
    }
})(jQuery);